/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package yassp.server;

import yassp.*;

import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author pierre
 */
public class ServerConnection extends Thread {

    private Socket client;
    private String login;
    private String root;
    private int state;

    private int blockSize=8; // blocksize temporary hardcoded
    private byte [] buf  = new byte [blockSize];
    // files streams
    private BufferedInputStream bis;
    private BufferedOutputStream bos;

    //commands streams
    private BufferedReader in = null;
    private PrintStream out = null;

    public ServerConnection(Socket client) {
        this.client = client;
//        try {
//            /* obtain an input stream to this client ... */
//            in = new BufferedReader(new InputStreamReader(
//                        client.getInputStream()));
//            /* ... and an output stream to the same client */
//            out = new PrintWriter(client.getOutputStream(), true);
//        } catch (IOException e) {
//            System.err.println(e);
//            return;
//        }

        try {
            bis = new BufferedInputStream(client.getInputStream());
            bos = new BufferedOutputStream(client.getOutputStream());
        } catch (Exception e) {
            System.out.println("Error: can't create I/O Streams for client: "+client);
        }
    }

    @Override
    public void run(){
        System.out.println("Starting thread");

        authentication();
        DataInputStream dis = new DataInputStream(bis);
        DataOutputStream dos = new DataOutputStream(bos);
        
        while(!client.isClosed()){
            try {
                int code = dis.readInt();
                String folder;
                String hash;
                switch(code) {
                    case Code.PUSHFILE:
                        hash = dis.readUTF();
                        Long size = dis.readLong();
                        PipedOutputStream pos = new PipedOutputStream();
                        PipedInputStream pis = new PipedInputStream(pos);
                        BlobStore.store(hash,pis);
                        
                        byte[] buffer = new byte[256];
                        while(size > 0){
                            int c = bis.read(buf, 0, (int)Math.min(256, size));
                            if(c == -1)
                                return;
                            size -= c;
                            pos.write(buf, 0, c);
                        }
                        pos.close();
                        break;
                        
                        
                    case Code.PULLFILE:
                        hash = dis.readUTF();
                        if(BlobStore.hasHash(hash)){
                            dos.writeInt(Code.OK);
                            BlobStore.retrieve(hash,bos);
                        } else {
                            dos.writeInt(Code.NOK);
                        }
                        break;
                        
                    case Code.PUSHFOLDER:
                    case Code.PUSHROOT:
                        folder = dis.readUTF();
                        BlobStore.storeFolder(folder.split("\n\n")[0].split(":", 2)[1],folder);
                        dos.writeInt(Code.OK);
                        break;
                        
                    case Code.PULLFOLDER:
                        folder = dis.readUTF();
                        folder = BlobStore.retrieveFolder(folder);
                        if(!folder.equals("")) {
                            dos.writeInt(Code.OK);
                            dos.writeUTF(folder);
                        } else {
                            dos.writeInt(Code.NOK);
                        }
                        break;
                }
                
            } catch (IOException ex) {
                Logger.getLogger(ServerConnection.class.getName()).log(Level.SEVERE, null, ex);
                try {
                    client.close();
                } catch (IOException ex1) {
                    Logger.getLogger(ServerConnection.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }
    
        }

    }

    boolean authentication(){
        return true;
    }

}
